package com.block.merchant.service.impl;

import cn.hutool.core.thread.ThreadUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.block.common.annotate.RedisLock;
import com.block.common.exception.NotifyExceptionService;
import com.block.common.util.ApplicationContextUtil;
import com.block.db.entity.MerchantBaseInfo;
import com.block.db.entity.MerchantDataPushCountInfo;
import com.block.db.mapper.MerchantBaseInfoMapper;
import com.block.db.mapper.MerchantDataPushCountInfoMapper;
import com.block.merchant.model.dto.DataPushCountDTO;
import com.block.merchant.service.IMerchantDataPushCountInfoService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.sql.Struct;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Date;
import java.util.concurrent.TimeUnit;

/**
 * <p>
 * 商户推送结果统计 服务实现类
 * </p>
 *
 * @author
 * @since 2024-03-14
 */
@Service
public class MerchantDataPushCountInfoServiceImpl extends ServiceImpl<MerchantDataPushCountInfoMapper, MerchantDataPushCountInfo> implements IMerchantDataPushCountInfoService {

    @Resource
    MerchantDataPushCountInfoMapper merchantDataPushCountInfoMapper;
    @Resource
    MerchantBaseInfoMapper merchantBaseInfoMapper;

    @Autowired
    NotifyExceptionService notifyExceptionService;
    @Autowired
    StringRedisTemplate stringRedisTemplate;


    private String REDIS_LOCK_KEY = "MERCHANT:DATA:COUNT:{}";

    @Override
    @Async
    @Transactional
    public void updateDatePushCountInfo(DataPushCountDTO dataPushCountDTO) {
        MerchantDataPushCountInfo dataPushCountInfo = merchantDataPushCountInfoMapper.selectEntityByInfoIdAndDateInfoLock(dataPushCountDTO.getInfoId(), dataPushCountDTO.getDateInfo());
        if (ObjectUtil.isEmpty(dataPushCountInfo)) {

            String redisKey = StrUtil.format(REDIS_LOCK_KEY + dataPushCountDTO.getInfoId());
            boolean locked = stringRedisTemplate.opsForValue()
                    .setIfAbsent(redisKey, "1",5 , TimeUnit.SECONDS);
            if (locked){
                dataPushCountInfo = new MerchantDataPushCountInfo();
                dataPushCountInfo.setDateInfo(dataPushCountDTO.getDateInfo());
                dataPushCountInfo.setInfoId(dataPushCountDTO.getInfoId());
                dataPushCountInfo.setInfoName(dataPushCountDTO.getInfoName());
                boolean save = this.save(dataPushCountInfo);
                if (!save) {
                    // TODO: 2024/3/14 异常通知
                    System.out.println("保存失败");
                    return;
                }
                System.out.println("保存成功");
                dataPushCountInfo = merchantDataPushCountInfoMapper.selectEntityByInfoIdAndDateInfoLock(dataPushCountDTO.getInfoId(), dataPushCountDTO.getDateInfo());
            }else {
                ThreadUtil.safeSleep(3000);
                dataPushCountInfo = merchantDataPushCountInfoMapper.selectEntityByInfoIdAndDateInfoLock(dataPushCountDTO.getInfoId(), dataPushCountDTO.getDateInfo());
                if (ObjectUtil.isEmpty(dataPushCountInfo)) {
                    // TODO: 2024/3/14 异常通知
                    System.out.println("二次查询为空值");
                }
            }
        }

        MerchantDataPushCountInfo updateEntity = new MerchantDataPushCountInfo();
        updateEntity.setId(dataPushCountInfo.getId());

        if (ObjectUtil.isNotEmpty(dataPushCountDTO.getCheckNumber())) {
            updateEntity.setCheckNumber(dataPushCountDTO.getCheckNumber() + dataPushCountInfo.getCheckNumber());
        }

        if (ObjectUtil.isNotEmpty(dataPushCountDTO.getCheckSuccessNumber())) {
            updateEntity.setCheckSuccessNumber(dataPushCountDTO.getCheckSuccessNumber() + dataPushCountInfo.getCheckSuccessNumber());
        }

        if (ObjectUtil.isNotEmpty(dataPushCountDTO.getRegisterNumber())) {
            updateEntity.setRegisterNumber(dataPushCountDTO.getRegisterNumber() + dataPushCountInfo.getRegisterNumber());
        }

        if (ObjectUtil.isNotEmpty(dataPushCountDTO.getRegisterSuccessNumber())) {
            updateEntity.setRegisterSuccessNumber(dataPushCountDTO.getRegisterSuccessNumber() + dataPushCountInfo.getRegisterSuccessNumber());
        }

        this.updateById(updateEntity);

        MerchantDataPushCountInfo updatedInfo = merchantDataPushCountInfoMapper.selectById(dataPushCountInfo.getId());

        // TODO: 2024/3/14 实时监测机构进件成功率，通知报警
        //      RegisterSuccessNumber / RegisterNumber < 85% 报警通知

//        if (updatedInfo.getRegisterNumber() != 0) {
//            //如果是钱满贷机构，失败一条直接关掉
////            int failed = updatedInfo.getRegisterNumber().intValue() - updatedInfo.getRegisterSuccessNumber().intValue();
////            if (dataPushCountDTO.getInfoId() == 139 && failed >= 1){
////                MerchantBaseInfo merchantBaseInfo = new MerchantBaseInfo();
////                merchantBaseInfo.setId(dataPushCountDTO.getInfoId());
////                merchantBaseInfo.setStatus(0);
////                merchantBaseInfo.setUpdateTime(LocalDateTime.now());
////                merchantBaseInfoMapper.updateById(merchantBaseInfo);
////            }
//            //失败率
//            double successRate = (double) updatedInfo.getRegisterSuccessNumber() / updatedInfo.getRegisterNumber();
//            if (successRate < 0.85) {
//                String content = StrUtil.format("【infoId】{}【infoName】{} 【进件成功率】{} ", updatedInfo.getInfoId(), updatedInfo.getInfoName(), successRate);
//                notifyExceptionService.notifyNoticeInfo("DATA_PUSH_COUNT_INFO", "商户进件率过低", content, null);
//            }
//        }
    }

    @Override
    @RedisLock(lockName = "MERCHANT:DATA:COUNT:", key = "#infoId" )
    public boolean saveDatePushCountInfo(MerchantDataPushCountInfo dataPushCountInfo, String infoId) {
        return this.save(dataPushCountInfo);
    }



}
